package com.vcc.web.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.hutool.core.util.IdUtil;
import com.vcc.core.annotations.KycReject;
import com.vcc.core.annotations.ROReject;
import com.vcc.core.annotations.RestPack;
import com.vcc.core.exception.ProgramException;
import com.vcc.data.entity.TransferOrder;
import com.vcc.data.entity.User;
import com.vcc.data.entity.Wallet;
import com.vcc.service.client.dto.wellat.TransferOutDto;
import com.vcc.service.client.vo.wellat.WalletVo;
import com.vcc.service.service.*;
import com.vcc.web.core.component.UserComponent;
import com.vcc.web.core.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("wallet")
public class WalletController {

    @Autowired
    private WalletService walletService;
    @Autowired
    private WalletDetailService walletDetailService;
    @Autowired
    private UserService userService;
    @Autowired
    private CurrencyService currencyService;
    @Autowired
    private TransferOrderService transferOrderService;
    @Autowired
    private UserComponent userComponent;

    @RestPack
    @GetMapping("refreshUsableQuota")
    public List<WalletVo> refreshUsableQuota() {
        Long userId = UserUtil.getId();
        List<Wallet> wallets = walletService.listByUserId(userId);
        return wallets.stream().map(WalletVo::new).collect(Collectors.toList());
    }

    @RestPack
    @GetMapping("getUserWallet")
    public List<WalletVo> getUserWallet(Long targetUserId) {
        Long userId = UserUtil.getId();
        User targetUser = userService.getByIdOpt(targetUserId).orElseThrow(() -> new ProgramException("用户不存在"));
        userComponent.verifyUserDataPermission(targetUserId);
        List<Wallet> wallets = walletService.listByUserId(targetUser.getId());
        return wallets.stream().map(WalletVo::new).collect(Collectors.toList());
    }

    //当前操作角色  操作用户  被操作用户


//    @RestPack
//    @ROReject
//    @KycReject
//    @SaCheckPermission("wallet:edit:rate")
//    @PostMapping("updateRate")
//    public Boolean updateRate(
//            @RequestBody UpdateRateDto updateRateDto) {
//        Long userId = UserUtil.getId();
//        Role role = UserUtil.getRole();
//        if (userId.equals(updateRateDto.getUserId())) {
//            throw new ProgramException("无法自己变更自己的费率");
//        }
//        User user = userService.getById(updateRateDto.getUserId());
//        if (!user.getBeLongToDealer().equals(userId)) {
//            throw new ProgramException("当前帐号不归属与您。无法修改");
//        }
//        if (updateRateDto.getRate().compareTo(BigDecimal.valueOf(0)) <= 0) {
//            throw new ProgramException("费率不能小于等于0");
//        }
//        Wallet wallet = walletService.getById(updateRateDto.getWallerId());
//        if (wallet.getExchangeRate().compareTo(updateRateDto.getRate()) == 0) {
//            throw new ProgramException("汇率一致无需修改");
//        }
//        return null;
//    }


    @RestPack
    @ROReject
    @KycReject
    @SaCheckPermission("wallet:transfer")
    @PostMapping("transfer")
    @SaCheckSafe("TRANSFER_CREATE")
    public Boolean transferOut(@RequestBody @Validated TransferOutDto transferOutDto) {
        String outOrderId = IdUtil.getSnowflakeNextIdStr();
        String inOrderId = IdUtil.getSnowflakeNextIdStr();
        Wallet inWallet = walletService.getNotRateWalletById(transferOutDto.getInWalletId());
        Wallet outWallet = walletService.getNotRateWalletById(transferOutDto.getOutWalletId());
        userComponent.verifyUserDataPermission(inWallet.getUserId());
        userComponent.verifyUserDataPermission(outWallet.getUserId());
        BigDecimal balance = walletService.subtractUsableQuotaById(
                outWallet.getId(),
                transferOutDto.getAmount(),
                2,
                false
        );
        TransferOrder outTransferOrder = TransferOrder.builder()
                .userId(outWallet.getUserId())
                .walletId(outWallet.getId())
                .amount(transferOutDto.getAmount())
                .status(0)
                .type("out")
                .remark(transferOutDto.getRemark())
                .orderId(outOrderId)
                .currency(outWallet.getCurrencyCode())
                .operateId(UserUtil.getId())
                .build();
        transferOrderService.save(outTransferOrder);
        walletDetailService.transferOut(
                outOrderId,
                transferOutDto.getRemark(),
                transferOutDto.getAmount(),
                balance,
                outWallet.getCurrencyId(),
                outWallet.getUserId()
        );
        TransferOrder inTransferOrder = TransferOrder.builder()
                .userId(inWallet.getUserId())
                .walletId(inWallet.getId())
                .amount(transferOutDto.getAmount())
                .status(0)
                .type("in")
                .remark(transferOutDto.getRemark())
                .orderId(inOrderId)
                .currency(inWallet.getCurrencyCode())
                .operateId(UserUtil.getId())
                .build();
        transferOrderService.save(inTransferOrder);
        BigDecimal targetBalance = walletService.addUsableQuotaById(
                inWallet.getId(),
                transferOutDto.getAmount(),
                1,
                false
        );
        walletDetailService.transferIn(
                inOrderId,
                transferOutDto.getRemark(),
                transferOutDto.getAmount(),
                targetBalance,
                inWallet.getCurrencyId(),
                inWallet.getUserId()
        );
        return true;
    }

}
